package com.otp.service.util;

import java.util.Collections;
import java.util.List;
import java.util.ArrayList;
import java.util.Stack;

public class HTMLTagParsing {

	public static List<String> parseHTML(String str, List<String> openTags, List<String> closeTags, Integer[] codes){

		int tagTypeCount = openTags.size();
		List<HTMLTag> tags = new ArrayList<HTMLTag>();
		List<String> substrings = new ArrayList<String>();

		//Compile and sort tag list
		for(int i=0;i<tagTypeCount;i++){
			int index=str.indexOf(openTags.get(i));
			while(index!=-1){
				HTMLTag tag = new HTMLTag(index,i,false);
				tags.add(tag);
				index=str.indexOf(openTags.get(i),index+1);
			}
			index=str.indexOf(closeTags.get(i));
			while(index!=-1){
				HTMLTag tag = new HTMLTag(index,i,true);
				tags.add(tag);
				index=str.indexOf(closeTags.get(i),index+1);
			}
			Collections.sort(tags,new HTMLTagComparator());
		}
		
		if(tags.isEmpty()) {substrings.add(str); codes[0]=0; return substrings;}

		//Compile crude substring list
		substrings.add(str.substring(0,tags.get(0).getIndex()).trim());
		int i;
		for(i=0; i<tags.size()-1; i++){
			HTMLTag tag = tags.get(i);
			int leftIndex;
			int rightIndex;
			if(tag.isClosing()) leftIndex=tag.getIndex()+closeTags.get(tag.getTypeNo()).length();
			else leftIndex=tag.getIndex()+openTags.get(tag.getTypeNo()).length();
			rightIndex= tags.get(i+1).getIndex();
			substrings.add(str.substring(leftIndex,rightIndex).trim());
		}
		HTMLTag tag1 = tags.get(i);
		int leftIndex1;
		if(tag1.isClosing()) leftIndex1=tag1.getIndex()+closeTags.get(tag1.getTypeNo()).length();
		else leftIndex1=tag1.getIndex()+openTags.get(tag1.getTypeNo()).length();
		substrings.add(str.substring(leftIndex1).trim());

		//Parsing procceds - evaluate codes
		@SuppressWarnings("unchecked")
		Stack<Integer>[] stacks = new Stack[tagTypeCount];
		for(i=0; i<tagTypeCount;i++) stacks[i]=new Stack<Integer>();
		for(i=0; i<tags.size()+1; i++) codes[i]=0; 
		
		for(i=0; i<tags.size(); i++){
			int left;
			int right;
			HTMLTag tag=tags.get(i);
			Stack<Integer> stack = stacks[tag.getTypeNo()];
			if(tag.isClosing()){
				if(stack.isEmpty()) return null;
				else{
					left=stack.pop();
					right=i;
					if(stack.isEmpty()){
						int powerResult = 1;
						for(int i1 = 0; i1 < tag.getTypeNo(); i1++) powerResult*=2;
						for(int i2=left; i2<=right; i2++) codes[i2]+=powerResult;
					}
				}
			}else{
				stack.push(i+1);
			}
		}
				
		//Consolidate results
		List<String> result = new ArrayList<String>();
		i=0;//i refers to the unconsolidated string list
		int j=0;//j refers to the consolidated string list
		while(i<substrings.size()){
			String currString = substrings.get(i);
			if(currString.isEmpty()) {i++; continue;}
			Integer currCode = codes[i];
			i++;
			while(currCode==codes[i]&&i<substrings.size()){
				if(substrings.get(i).isEmpty()) {i++; continue;}
				currString+=" "+substrings.get(i);
				i++;
			}
			result.add(currString);
			codes[j++]=currCode;
		}		
		for(int k=j; k<substrings.size(); k++) codes[k]=0;
		
		return result;
	}		
}


	
